package com.weizhu.swufer.core.grpc;

import com.weizhu.swufer.core.entity.RpcBaseInfo;
import com.weizhu.swufer.core.rpc.RpcEngine;
import com.weizhu.swufer.grpc.GrpcCommonServiceGrpc;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.netty.NettyServerBuilder;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.io.IOException;
import java.net.BindException;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;

public class GrpcServer  {

    private transient Server ioGrpcServer;

    private final Properties properties;

    private int grpcPort;

    private ThreadPoolTaskExecutor bizExecutor;

    private final static int DEFAULT_PORT = 1025;

    private GrpcCommonServiceGrpc.GrpcCommonServiceImplBase grpcService;

    public GrpcServer(Properties properties){
        this.properties = properties;

    }

    public void initServer(ConcurrentHashMap<String, RpcBaseInfo> localServiceMap) {
        grpcService = new GrpcCommonServerImpl(localServiceMap);
        System.err.println("<==========grpc服务器已初始化===========>");
        if (properties.getProperty("port") == null || properties.getProperty("port").isEmpty()){
            grpcPort = DEFAULT_PORT;
        }
        grpcPort = Integer.parseInt(properties.getProperty("port"));
        initExecutor();
    }

    private void initExecutor() {
        if (bizExecutor != null){
            return;
        }
        bizExecutor = new ThreadPoolTaskExecutor();
        bizExecutor.setCorePoolSize(50);
        bizExecutor.setMaxPoolSize(200);
        bizExecutor.setQueueCapacity(10000);
        bizExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        bizExecutor.setDaemon(false);
        bizExecutor.initialize();
    }

    public void start() throws IOException {
        ServerBuilder<?> build = NettyServerBuilder.forPort(grpcPort).executor(bizExecutor);
        build.addService(grpcService);
        this.ioGrpcServer = build.build();
        ioGrpcServer.start();
        System.err.println("<==========grpc服务器已开启===========>"+grpcPort);
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.err.println("<===== shutting down gRPC server since JVM is shutting down =====>");
                if (RpcEngine.getInstance().getBarrier().compareAndSet(0,1)){
                    if (GrpcCommonServerImpl.getLocalMetrics().getActive().get() > 0){
                        System.err.println("open barrier,waiting for request handle...");
                        long start = System.currentTimeMillis();
                        while (System.currentTimeMillis() - start < 1000 * 12 &&
                                GrpcCommonServerImpl.getLocalMetrics().getActive().get() > 0){
                        }
                    }
                    ioGrpcServer.shutdown();
                    System.err.println("<===== server shut down =====>");

                }
            }
        });
    }
}
